package com.evil.kingdom.utils;

import com.alibaba.fastjson.JSONObject;
import com.evil.common.core.exception.BusinessException;
import com.evil.kingdom.constant.RedisConstant;
import com.evil.kingdom.pojo.entity.token.SocketInfo;
import com.evil.kingdom.pojo.entity.token.TokenInfo;
import com.evil.kingdom.pojo.enums.result.RCodeEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author liyang
 * @date 2023-01-08 12:43
 */
@Slf4j
@Component
@AllArgsConstructor
public class TokenUtil {

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 存token
     *
     * @param token     token
     * @param tokenInfo tokenInfo
     */
    public void setTokenInfo(String token, TokenInfo tokenInfo) {
        redisTemplate.opsForValue().set(RedisKeyUtil.accessTokenKey(token), tokenInfo, RedisConstant.TOKEN_EXPIRE_IN_SECOND, TimeUnit.SECONDS);
    }

    /**
     * 移除token
     *
     * @param token token
     */
    public boolean detTokenInfo(String token) {
        return BooleanUtils.isTrue(redisTemplate.delete(RedisKeyUtil.accessTokenKey(token)));
    }

    /**
     * 存socket token
     *
     * @param token      token
     * @param socketInfo socketInfo
     */
    public void setSocket(String token, SocketInfo socketInfo) {
        redisTemplate.opsForValue().set(RedisKeyUtil.socketTokenKey(token), socketInfo, RedisConstant.TOKEN_EXPIRE_IN_SECOND, TimeUnit.SECONDS);
    }

    /**
     * 移除socket token
     *
     * @param token token
     */
    public boolean detSocket(String token) {
        return BooleanUtils.isTrue(redisTemplate.delete(RedisKeyUtil.socketTokenKey(token)));
    }

    /**
     * 获取token
     *
     * @return TokenInfo
     */
    public TokenInfo findTokenInfo(String token) {
        return this.isExistTokenInfo(token).orElseThrow(() -> new BusinessException(RCodeEnum.ERROR_UNAUTHENTICATED));
    }

    /**
     * 获取token
     *
     * @return TokenInfo
     */
    public Optional<TokenInfo> isExistTokenInfo(String token) {
        Object o;
        try {
            o = redisTemplate.opsForValue().get(RedisKeyUtil.accessTokenKey(token));
        } catch (Exception e) {
            log.error("isExistTokenInfo| error: ", e);
            return Optional.empty();
        }
        TokenInfo tokenInfo = null;
        if (o instanceof TokenInfo) {
            tokenInfo = (TokenInfo) o;
        }
        if (o instanceof JSONObject jsonObject) {
            tokenInfo = jsonObject.toJavaObject(TokenInfo.class);
        }
        return Optional.ofNullable(tokenInfo);
    }

    /**
     * 获取websocket认证信息
     *
     * @param token token
     * @return IP
     */
    public SocketInfo findSocket(String token) {
        return this.isExistSocket(token).orElseThrow(() -> new BusinessException(RCodeEnum.SOCKET_ERROR));
    }

    /**
     * 获取websocket认证信息
     *
     * @param token token
     * @return IP
     */
    public Optional<SocketInfo> isExistSocket(String token) {
        Object o;
        try {
            o = redisTemplate.opsForValue().get(RedisKeyUtil.socketTokenKey(token));
        } catch (Exception e) {
            log.error("isExistToken| error: ", e);
            return Optional.empty();
        }
        SocketInfo socketInfo = null;
        if (o instanceof SocketInfo) {
            socketInfo = (SocketInfo) o;
        }
        if (o instanceof JSONObject jsonObject) {
            socketInfo = jsonObject.toJavaObject(SocketInfo.class);
        }
        return Optional.ofNullable(socketInfo);
    }
}
